package com.abc.core.tool;

import com.abc.core.annotations.DnaDef;
import com.abc.core.annotations.VarDef;
import com.abc.core.consts.CellFixedName;
import com.abc.core.def.Dna;
import com.abc.core.instance.bo.Cell;
import com.abc.core.instance.bo.Inst;
import com.abc.demo.PartyBO;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

public class DnaAnnotationUtil {
    private static <T> List<T> inst2Objects(Inst inst, Class<T> clazz) {
        DnaDef annotation = getDnaAnnotation(clazz);
        ArrayList<T> results = new ArrayList<T>();

        Dna dna = inst.getDna();

        for (Cell cell : inst.getCells()) {
            T obj = createObject(clazz);
            for (Field f : clazz.getDeclaredFields()) {
                String vdName = f.getName();
                VarDef vdAnnotation = (VarDef) f.getDeclaredAnnotation(VarDef.class);
                if (vdAnnotation == null) {
                    continue;
                }

                String name = vdAnnotation.value();
                if (name != null && !name.equals("") && name.equals(CellFixedName.ID)) {
                    setObjectValue(obj, vdName, cell.getId());
                } else if (name != null && !name.equals("")) {
                    setObjectValue(obj, vdName, cell.getValue(name));
                } else if (name == null || name.equals("")) {
                    // 如果是下一个Dna
                    String childDnaName = vdAnnotation.dnaName();
                    if (childDnaName == null || childDnaName.equals("")) {
                        continue;
                    }

                    Dna childDna = dna.getDnaByName(childDnaName);
                    if (childDna == null) {
                        if (dna.isCursive() && dna.getDnaName().equals(childDnaName)) {
                            childDna = dna;
                        } else {
                            continue;
                        }
                    }

                    if (f.getType().isAssignableFrom(List.class)) {
                        Inst childInst = cell.getChildInst(childDna.getDnaName());
                        ParameterizedType pt = (ParameterizedType) f.getGenericType();
                        String typeName = pt.getActualTypeArguments()[0].getTypeName();
                        Class childClazz = getClassByClassName(typeName);
                        List children = inst2Objects(childInst, childClazz);
                        if (children != null) {
                            setObjectValue(obj, vdName, children);
                        }
                    } else {
                        throw new RuntimeException("不支持的属性类型:" + f.getType().getName());
                    }
                }
            }
            results.add(obj);
        }
        return results;
    }

    private static <T> DnaDef getDnaAnnotation(Class<T> clazz) {
        return null;
    }

    private static <T> T createObject(Class<T> clazz) {
        return null;
    }

    private static Class getClassByClassName(String typeName) {
        return null;
    }

    private static void setObjectValue(Object obj, String name, Object value) {
        try {
            Field f = obj.getClass().getDeclaredField(name);
            try {
                f.setAccessible(true);
                f.set(obj, value);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    /**
     * Inst实例到单个POJO对象的转换 p.66
     *
     * @param <T>
     * @param inst
     * @param clazz
     * @return
     */
    public static <T> T inst2Object(Inst inst, Class<T> clazz) {
        if (inst == null || inst.getCells().isEmpty()) {
            return null;
        } else if (inst.getCells().size() == 1) {
            List<T> results = inst2Objects(inst, clazz);
            return (results != null && results.size() > 0) ? results.get(0) : null;
        }
        throw new RuntimeException("输入参数cells个数不能大于1");
    }

    /**
     * 将POJO 对象转换成Inst对象 p.66
     *
     * @param <T>
     * @param objs
     * @param parentDna
     * @return
     */
    public static <T> Inst objects2Inst(List<T> objs, Dna parentDna) {
        if (objs == null || objs.size() == 0) {
            return null;
        }

        Inst inst = null;
        for (T obj : objs) {

        }

        // TODO p.66
        return null;
    }

    public static <T> Inst objecjt2Inst(T obj, Dna parentDna) {
        List<T> list = new ArrayList<T>();
        list.add(obj);
        return objects2Inst(list, parentDna);
    }

    public static Inst object2Inst(PartyBO partyBO, Object o) {
        //TODO
        return null;
    }
}
